package com.zym.framework.grid;

import com.alibaba.fastjson.JSONObject;
import javafx.beans.NamedArg;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.TableColumn;
import javafx.util.Callback;

import java.math.BigDecimal;

/**
 * QQ 165149324
 * 臧英明
 *
 * @author
 * @create 2021-03-01
 */
public class JSONObjectCell<T> implements Callback<TableColumn.CellDataFeatures<JSONObject,T>, ObservableValue<T>> {
    private final Object key;

    /**
     * Creates a default MapValueFactory, which will use the provided key to
     * lookup the value for cells in the {@link TableColumn} in which this
     * MapValueFactory is installed (via the
     * {@link TableColumn#cellValueFactoryProperty() cell value factory} property.
     *
     * @param key The key to use to lookup the value in the {@code Map}.
     */
    public JSONObjectCell(final @NamedArg("key") Object key) {
        this.key = key;
    }

    @Override public ObservableValue<T> call(TableColumn.CellDataFeatures<JSONObject, T> cdf) {
        JSONObject map = cdf.getValue();
        Object value = map.get(key);

        // ideally the map will contain observable values directly, and in which
        // case we can just return this observable value.


        // TODO
        // If we are here, the value in the map for the given key is not observable,
        // but perhaps the Map is an ObservableMap. If this is the case, we
        // can add a listener to the map for the given key, and possibly observe
        // it for changes and return these
//        if (map instanceof ObservableMap) {
//            ObservableMap oMap = (ObservableMap) map;
//            // ....
//        }

        // Often time there is special case code to deal with specific observable
        // value types, so we try to wrap in the most specific type.
        if (value instanceof Boolean) {
            return (ObservableValue<T>) new ReadOnlyBooleanWrapper((Boolean)value);
        } else if (value instanceof Integer) {
            return (ObservableValue<T>) new ReadOnlyIntegerWrapper((Integer)value);
        } else if (value instanceof Float) {
            return (ObservableValue<T>) new ReadOnlyFloatWrapper((Float)value);
        } else if (value instanceof Long) {
            return (ObservableValue<T>) new ReadOnlyLongWrapper((Long)value);
        } else if (value instanceof Double) {
            return (ObservableValue<T>) new ReadOnlyDoubleWrapper((Double)value);
        } else if (value instanceof String) {
            return (ObservableValue<T>) new ReadOnlyStringWrapper((String)value);
        } else if(value instanceof BigDecimal){
            BigDecimal bd = (BigDecimal) value;
            return  new ReadOnlyObjectWrapper((bd.doubleValue()));
        }

        // fall back to an object wrapper
        return new ReadOnlyObjectWrapper<T>((T)value);
    }
}
